/*
    This source file is part of GeNa project.
    Copyright © GeNa project 2008
    For the latest info, see http://code.google.com/p/genaproject/ or  http://lumpyproject.forums-rpg.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Foobar is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Foobar.  If not, see <http://www.gnu.org/licenses/>. */

#ifndef SERIALIZED_DATA_H_INCLUDED
#define SERIALIZED_DATA_H_INCLUDED

#include "wx_pch.h"
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/basic_archive.hpp>
#include <boost/serialization/base_object.hpp>
using namespace boost::archive;
using namespace boost::serialization;

class SerializedData : public wxDataObjectSimple
{
    std::string str;
    std::istringstream* _istr;
    binary_iarchive* _iarch;
    std::ostringstream* _ostr;
    binary_oarchive* _oarch;

public:
    SerializedData( wxString name) : wxDataObjectSimple(wxDataFormat(name))
    {
        _istr = NULL;
        _ostr = NULL;
        _iarch = NULL;
        _oarch = NULL;
    }

    SerializedData(const wxDataFormat &format) : wxDataObjectSimple(format)
    {
        _istr = NULL;
        _ostr = NULL;
        _iarch = NULL;
        _oarch = NULL;
    }

    void flush()
    {
        if( _ostr)
            const_cast<std::string&>(str) = _ostr->str();
    }

    size_t GetDataSize() const
    {
        return str.length();
    }

    bool GetDataHere(void *buf) const
    {

        char* a = (char*)buf;
        for( unsigned int i=0; i<str.length();i++)
            a[i] = str[i];
        return true;
    }

    bool SetData(size_t len, const void *buf)
    {
        const char* a = (const char*)buf;
        for( unsigned int i=0; i<len;i++)
            str += a[i];
        return true;
    }

    template<class T>  void copy(const T& in)
    {
        std::ostringstream out;
        binary_oarchive archive(out);
        archive << in;
        str = out.str();
    }

    template<class T>  void paste(T& out)
    {
        std::istringstream in(str);
        binary_iarchive archive(in);
        archive >> out;
    }

    template<class T>  void copy2(const T& in)
    {
        _ostr = new std::ostringstream;
        _oarch = new binary_oarchive(*_ostr);
        (*_oarch) << in;
        //str = _ostr->str();
    }

    template<class T>  void paste2(T& out)
    {
        std::istringstream in(str);
        binary_iarchive archive(in);
        archive >> out;
    }

    binary_oarchive * openCopyArchive()
    {
        _ostr = new std::ostringstream;
        _oarch = new binary_oarchive(*_ostr);
        return _oarch;
    }

    binary_iarchive * openPasteArchive()
    {
        _istr = new std::istringstream(str);
        _iarch = new binary_iarchive(*_istr);
        return _iarch;
    }

    template<class T> SerializedData& operator<<(const T& in)
    {
        if( !_oarch)
            openCopyArchive();
        *_oarch << in;
        const_cast<std::string&>(str) = _ostr->str();
        return *this;
    }

    template<class T> SerializedData& operator>>(T& out)
    {
        if( !_iarch)
            openPasteArchive();
        *_iarch >> out;
        return *this;
    }

    ~SerializedData()
    {
        if( _istr)
        {
            delete _iarch;
            delete _istr;
        }

        if( _ostr)
        {
            delete _oarch;
            delete _ostr;
        }
    }
};

#endif // SERIALIZED_DATA_H_INCLUDED
